/**
 * Area de Composicao do Layout de um Mapa
 *
 * @this {UIMapLayoutArea}
 * @version
 */

function UIMapLayoutArea() {

    /**
     * Variaveis
     */
    var _elementTypeToDraw = EElementType.eNone;
    var _svgDocument = null;
    var _svgContent = null;
    var _svgElements = null;
    var _selectedVertexResizerId = null;
    var _svgImageElementTemplate = null;
    var _svgLabelElementTemplate = null;
    var _oClassOwner = this;

    /**
     * Inicializa o objeto da classe
     */
    this.init = function() {
        
    }

    /**
     * Funcoes
     */
    
    this.initSVGLayout = function() {

        //inicializa e prepara o layout em svg para receber os eventos de composicao
        _svgDocument = document.getElementById("svgobject").getSVGDocument();
        _svgContent = _svgDocument.getElementById("svgcontent");
        _svgElements = _svgDocument.getElementById("svgelements");
        _svgDocument.getElementById("background").addEventListener("mousedown",this.start,false);
        _svgDocument.getElementById("background").addEventListener("click",this.onClickSVGLayout,false);
        //obtem os tipos de elemento-padrao em svg, para serem usados como "molde" durante a adicao de elementos no layout
        _svgImageElementTemplate = _svgDocument.getElementById("imageElementTemplate");
        _svgLabelElementTemplate = _svgDocument.getElementById("labelElementTemplate");
        //prepara e ativa os vertices do redimensionador de elementos
        _svgDocument.getElementById("vertexResizer_nw").addEventListener("mousedown",this.startResize,false);
        _svgDocument.getElementById("vertexResizer_ne").addEventListener("mousedown",this.startResize,false);
        _svgDocument.getElementById("vertexResizer_sw").addEventListener("mousedown",this.startResize,false);
        _svgDocument.getElementById("vertexResizer_se").addEventListener("mousedown",this.startResize,false);
    }

    /**
     * Inicia o processo de desenho do elemento no layout
     */
    this.start = function(evt){

        var oLayoutProject = ModelInstance.getLayoutProject();
        if(oLayoutProject.projectIsOpened()) {
            if(_elementTypeToDraw != EElementType.eNone) {
                _oClassOwner.trap(evt);
            }
        }
    }

    /**
     * Gerencia o estado de desenho do elemento no layout
     */
    this.trap = function(evt){

        var mousePosX = evt.clientX;
        var mousePosY = evt.clientY;
        
        //se clicou ou moveu sobre a area de layout
        if (evt.currentTarget.id == "background") {
            //realize o desenho
            _oClassOwner.begindraw(mousePosX, mousePosY);
            _svgDocument.addEventListener("mousemove",_oClassOwner.drawing,false);
        }
        else {
            var oLayoutComposer = ModelInstance.getLayoutComposer();
            oLayoutComposer.setSelectedElement(oLayoutComposer.getElementById(evt.currentTarget.id));
            //se clicou sobre um elemento svg, mova o elemento
            _svgDocument.addEventListener("mousemove",_oClassOwner.moving,false);
        }
        //finalize o desenho ou movimento do elemento sobre o layout
        _svgDocument.addEventListener("mouseup",_oClassOwner.finishdraw,false);
    }

    /**
     * Desenha o elemento no layout
     */
    this.begindraw = function(px, py){

        var oLayoutComposer = ModelInstance.getLayoutComposer();
        var oElement = null;

        if(_elementTypeToDraw != EElementType.eNone) {
            //cria um novo elemento
            oElement = oLayoutComposer.newElement(_elementTypeToDraw, px, py);
            if(oElement != null) {
                oLayoutComposer.addElement(oElement);
            }
        }
    }

    /**
     * Move o elemento selecionado no layout
     */
    this.moving = function(evt){

        var oLayoutComposer = ModelInstance.getLayoutComposer();
        var oElement = oLayoutComposer.getSelectedElement();

        if(oElement != null) {
            //posiciona o cursor do mouse sobre um elemento selecionado, para realizar o movimento
            switch(oElement.type) {

                case EElementType.eTImage:
                    oElement.x = evt.clientX - Math.abs(parseInt(oElement.width)/2);
                    oElement.y = evt.clientY - Math.abs(parseInt(oElement.height)/2);
                    oLayoutComposer.setSelectedElement(oElement);
                    _oClassOwner.editPropertiesSVGElement(oElement);
                    break;

                case EElementType.eTLabel:
                    oElement.x = evt.clientX;
                    oElement.y = evt.clientY;
                    oLayoutComposer.setSelectedElement(oElement);
                    _oClassOwner.editPropertiesSVGElement(oElement);
                    break;
            }
        }
        //atualiza a posicao do seletor de elemento
        _oClassOwner.setSelector();
    }

    /**
     * Desenha o elemento conforme movimento do cursor do mouse sobre o layout
     */
    this.drawing = function(evt){
    //...
    }

    /**
     * Finaliza o desenho do elemento no layout
     */
    this.finishdraw = function(evt){

        //desativa os eventos de desenho e movimento sobre um elemento
        _svgDocument.removeEventListener("mousemove",_oClassOwner.drawing,false);
        _svgDocument.removeEventListener("mousemove",_oClassOwner.moving,false);

        //atualiza as propriedades do elemento
        var oLayoutComposer = ModelInstance.getLayoutComposer();
        var oUIProperties = UIInstance.getUIPropertiesInstance();
        oLayoutComposer.editPropertiesElement(oLayoutComposer.getSelectedElement());
        oUIProperties.showProperties();
    }

    /**
     * Inicia o redimensionamento de um elemento
     */
    this.startResize = function(evt){

        var oLayoutComposer = ModelInstance.getLayoutComposer();
        var oElement = oLayoutComposer.getSelectedElement();
        if(oElement != null) {
            //define o vertice-redimensionador selecionado
            _selectedVertexResizerId = evt.currentTarget.id;
            //adiciona um evento que chama a rotina de aplicacao do redimensionamento,
            //quando o usuario mover o mouse (mousemove), e
            //adiciona um evento que chama a rotina de interrupcao do redimensionamento,
            //quando o usuario "soltar" o botao do mouse (mouseup).
            _svgDocument.getElementById(_selectedVertexResizerId).addEventListener("mousemove",_oClassOwner.resizing,false);
            _svgDocument.getElementById(_selectedVertexResizerId).addEventListener("mouseup",_oClassOwner.stopResize,false);
            _svgDocument.getElementById(oElement.id).addEventListener("mousemove",_oClassOwner.resizing,false);
            _svgDocument.getElementById(oElement.id).addEventListener("mouseup",_oClassOwner.stopResize,false);
            _svgDocument.getElementById("background").addEventListener("mousemove",_oClassOwner.resizing,false);
            _svgDocument.getElementById("background").addEventListener("mouseup",_oClassOwner.stopResize,false);
        }
    }

    /**
     * Aplica o redimensionamento no elemento
     */
    this.resizing = function(evt){

        var oLayoutComposer = ModelInstance.getLayoutComposer();
        var oElement = oLayoutComposer.getSelectedElement();
        if(oElement != null) {

            var svgElement = _svgDocument.getElementById(oElement.id);
            //posiciona o vertice de redimensionamento de acordo com a posicao do cursor do mouse
            _svgDocument.getElementById(_selectedVertexResizerId).setAttribute("cx", evt.clientX);
            _svgDocument.getElementById(_selectedVertexResizerId).setAttribute("cy", evt.clientY);

            var marginBetweenVertexAndSelBox = 4;  //em pixels
            var vx = null;
            var vy = null;
            //obtem o box do elemento
            var bbox = svgElement.getBBox();
            //obtem a posicao virtual da extremidade do elemento redimensionada,
            //de acordo com a posicao atual do cursor do mouse e o valor da margem
            //entre o vertice de redimensionamento e o box de selecao
            if(bbox.x > evt.clientX){
                vx = (evt.clientX+marginBetweenVertexAndSelBox);
            } else {
                vx = (evt.clientX-marginBetweenVertexAndSelBox);
            }
            if(bbox.y > evt.clientY){
                vy = (evt.clientY+marginBetweenVertexAndSelBox);
            } else {
                vy = (evt.clientY-marginBetweenVertexAndSelBox);
            }
                
            switch(_selectedVertexResizerId){

                case "vertexResizer_nw":
                    //calcula a diferenca de comprimento entre a extremidade do box e a posicao virtual
                    var dx = bbox.x - vx;
                    var dy = bbox.y - vy;
                    //calcula a nova escala do elemento
                    var scalex = (bbox.width+dx)/bbox.width;
                    var scaley = (bbox.height+dy)/bbox.height;
                    //calcula a nova dimensao virtual do elemento
                    var newdx = (bbox.x + bbox.width) - ((bbox.x + bbox.width)*scalex);
                    var newdy = (bbox.y + bbox.height) - ((bbox.y + bbox.height)*scaley);
                    //transforma o elemento svg, alterando sua matriz
                    svgElement.setAttribute("transform","matrix("+(scalex)+","+(0)+","+(0)+","+(scaley)+","+(newdx)+","+(newdy)+")");
                    break;

                case "vertexResizer_ne":
                    var dx = vx - (bbox.x + bbox.width);
                    var dy = bbox.y - vy;
                    var scalex = (bbox.width+dx)/bbox.width;
                    var scaley = (bbox.height+dy)/bbox.height;
                    var newdx = bbox.x - (bbox.x*scalex);
                    var newdy = (bbox.y + bbox.height) - ((bbox.y + bbox.height)*scaley);
                    svgElement.setAttribute("transform","matrix("+(scalex)+","+(0)+","+(0)+","+(scaley)+","+(newdx)+","+(newdy)+")");
                    break;

                case "vertexResizer_sw":
                    var dx = bbox.x - vx;
                    var dy = vy - (bbox.y + bbox.height);
                    var scalex = (bbox.width+dx)/bbox.width;
                    var scaley = (bbox.height+dy)/bbox.height;
                    var newdx = (bbox.x + bbox.width) - ((bbox.x + bbox.width)*scalex);
                    var newdy = bbox.y - (bbox.y*scaley);
                    svgElement.setAttribute("transform","matrix("+(scalex)+","+(0)+","+(0)+","+(scaley)+","+(newdx)+","+(newdy)+")");
                    break;

                case "vertexResizer_se":
                    var dx = vx - (bbox.x + bbox.width);
                    var dy = vy - (bbox.y + bbox.height);
                    var scalex = (bbox.width+dx)/bbox.width;
                    var scaley = (bbox.height+dy)/bbox.height;
                    var newdx = bbox.x - (bbox.x*scalex);
                    var newdy = bbox.y - (bbox.y*scaley);
                    svgElement.setAttribute("transform","matrix("+(scalex)+","+(0)+","+(0)+","+(scaley)+","+(newdx)+","+(newdy)+")");
                    break;
            }
        }
    }

    /**
     * Interrompe o redimensionamento do elemento
     */
    this.stopResize = function(evt){

        var oLayoutComposer = ModelInstance.getLayoutComposer();
        var oElement = oLayoutComposer.getSelectedElement();
        if(oElement != null) {
            //remove o evento cuja rotina aplica o redimensionamento (mousemove), e
            //remove o evento cuja rotina interrompe o redimensionamento (mouseup).
            _svgDocument.getElementById(evt.currentTarget.id).removeEventListener("mousemove",_oClassOwner.resizing,false);
            _svgDocument.getElementById(evt.currentTarget.id).removeEventListener("mouseup",_oClassOwner.stopResize,false);
            _svgDocument.getElementById(oElement.id).removeEventListener("mousemove",_oClassOwner.resizing,false);
            _svgDocument.getElementById(oElement.id).removeEventListener("mouseup",_oClassOwner.stopResize,false);
            _svgDocument.getElementById("background").removeEventListener("mousemove",_oClassOwner.resizing,false);
            _svgDocument.getElementById("background").removeEventListener("mouseup",_oClassOwner.finishdraw,false);

            var svgElement = _svgDocument.getElementById(oElement.id);
            var newPx = 0;
            var newPy = 0;
            var newWidth = 0;
            var newHeight = 0;
            var bbox = svgElement.getBBox();
            //obtem os valores que compoem a matriz do elemento svg
            var matrixValues = _oClassOwner.matrixStringToMatrixValues(svgElement.getAttributeNS(null, "transform"));

            //obtem a nova dimensao real do elemento, apos o redimensionamento
            switch(oElement.type){

                case EElementType.eTImage:
                    newPx = bbox.x;
                    newPy = bbox.y;
                    newWidth = bbox.width * matrixValues[0];
                    newHeight = bbox.height * matrixValues[3];
                    break;

                case EElementType.eTLabel:
                    newWidth = bbox.width * matrixValues[0];
                    newHeight = bbox.height * matrixValues[3];
                    newPx = bbox.x + Math.abs(newWidth/2);
                    newPy = bbox.y + Math.abs(newHeight/1.2);
                    break;
            }

            //corrige o posicionamento do elemento redimensionado
            switch(_selectedVertexResizerId){

                case "vertexResizer_nw":
                    (newWidth<0) ? newPx=(newPx+bbox.width) : newPx=((newPx+bbox.width)-Math.abs(newWidth));
                    (newHeight<0) ? newPy=(newPy+bbox.height) : newPy=((newPy+bbox.height)-Math.abs(newHeight));
                    break;

                case "vertexResizer_ne":
                    (newWidth<0) ? newPx=(newPx-Math.abs(newWidth)) : newPx=newPx;
                    (newHeight<0) ? newPy=(newPy+bbox.height) : newPy=((newPy+bbox.height)-Math.abs(newHeight));
                    break;

                case "vertexResizer_sw":
                    (newWidth<0) ? newPx=(newPx+bbox.width) : newPx=((newPx+bbox.width)-Math.abs(newWidth));
                    (newHeight<0) ? newPy=(newPy-Math.abs(newHeight)) : newPy=newPy;
                    break;

                case "vertexResizer_se":
                    (newWidth<0) ? newPx=(newPx-Math.abs(newWidth)) : newPx=newPx;
                    (newHeight<0) ? newPy=(newPy-Math.abs(newHeight)) : newPy=newPy;
                    break;
            }

            //transforma o elemento svg, recuperando sua matriz default
            svgElement.setAttribute("transform","matrix("+(1)+","+(0)+","+(0)+","+(1)+","+(0)+","+(0)+")");

            //define as novas dimensoes do elemento
            switch(oElement.type) {

                case EElementType.eTImage:
                    oElement.x = newPx;
                    oElement.y = newPy;
                    oElement.width = Math.abs(newWidth);
                    oElement.height = Math.abs(newHeight);
                    break;

                case EElementType.eTLabel:
                    oElement.x = newPx;
                    oElement.y = newPy;
                    oElement.fontSize = Math.abs(newHeight);
                    break;
            }
            oLayoutComposer.setSelectedElement(oElement);

            //define nenhum vertice-redimensionador selecionado
            _selectedVertexResizerId = null;
        }
    }

    /**
     * Define o posicionamento do selector de elemento
     */
    this.setSelector = function(){

        var oLayoutComposer = ModelInstance.getLayoutComposer();
        var oElement = oLayoutComposer.getSelectedElement();
        if(oElement != null) {
            
            var svgElement = _svgDocument.getElementById(oElement.id);
            //obtem o box do elemento
            var bbox = svgElement.getBBox();
            //obtem os novos vertices do box do seletor
            var newPx1 = bbox.x;
            var newPy1 = bbox.y;
            var newPx2 = bbox.x+bbox.width;
            var newPy2 = bbox.y+bbox.height;
            var vertexes = [newPx1,newPy1,newPx2,newPy1,newPx2,newPy2,newPx1,newPy2];
            //converte o conjunto de vertices em formato do atributo "path data" (d)
            //do tipo de elemento "path" (elemento nativo do SVG)
            var d = _oClassOwner.parseVertexesToDPath(vertexes);
            //define a nova posicao do box selector
            var svgBoxSelector = _svgDocument.getElementById("boxSelector");
            svgBoxSelector.setAttribute("d", d);
            //define a nova posicao dos vertices de redimensionamento
            var svgVertexResizerNW = _svgDocument.getElementById("vertexResizer_nw");
            svgVertexResizerNW.setAttribute("cx", newPx1);
            svgVertexResizerNW.setAttribute("cy", newPy1);
            var svgVertexResizerNE = _svgDocument.getElementById("vertexResizer_ne");
            svgVertexResizerNE.setAttribute("cx", newPx2);
            svgVertexResizerNE.setAttribute("cy", newPy1);
            var svgVertexResizerSW = _svgDocument.getElementById("vertexResizer_sw");
            svgVertexResizerSW.setAttribute("cx", newPx1);
            svgVertexResizerSW.setAttribute("cy", newPy2);
            var svgVertexResizerSE = _svgDocument.getElementById("vertexResizer_se");
            svgVertexResizerSE.setAttribute("cx", newPx2);
            svgVertexResizerSE.setAttribute("cy", newPy2);
            //mostra o seletor na area de layout
            this.showSelector();
        }
        else {
            //esconde o seletor da area de layout
            this.hideSelector();
        }
    }

    /**
     * Insere um elemento SVG no layout
     */
    this.insertSVGElement = function(oElement){

        var svgNewElement = null;
        
        if(oElement != null){

            switch(oElement.type){

                case EElementType.eTImage:
                    //cria o novo elemento SVG a partir de um elemento "molde" (padrao)
                    svgNewElement = _svgImageElementTemplate.cloneNode("false");
                    //define os atributos do elemento SVG a partir dos atributos de elemento da aplicacao
                    svgNewElement.setAttribute("id", oElement.id);
                    svgNewElement.setAttribute("x", oElement.x);
                    svgNewElement.setAttribute("y", oElement.y);
                    svgNewElement.setAttribute("width", oElement.width);
                    svgNewElement.setAttribute("height", oElement.height);
                    svgNewElement.setAttribute("xlink:href", oElement.href);
                    svgNewElement.setAttribute("style", oElement.style);
                    svgNewElement.addEventListener("mousedown",_oClassOwner.trap,false);
                    //adiciona o elemento SVG
                    _svgElements.appendChild(svgNewElement);
                    break;

                case EElementType.eTLabel:
                    svgNewElement = _svgLabelElementTemplate.cloneNode("false");
                    svgNewElement.setAttribute("id", oElement.id);
                    svgNewElement.setAttribute("x", oElement.x);
                    svgNewElement.setAttribute("y", oElement.y);
                    svgNewElement.setAttribute("font-size", oElement.fontSize);
                    svgNewElement.setAttribute("font-family", oElement.fontFamily);
                    svgNewElement.setAttribute("fill", oElement.fill);
                    svgNewElement.setAttribute("fill-opacity", oElement.fillOpacity);
                    svgNewElement.setAttribute("stroke", oElement.stroke);
                    svgNewElement.setAttribute("stroke-opacity", oElement.strokeOpacity);
                    svgNewElement.setAttribute("stroke-width", oElement.strokeWidth);
                    svgNewElement.setAttribute("text-anchor", oElement.textAnchor);
                    svgNewElement.setAttribute("style", oElement.style);
                    svgNewElement.setAttribute("xml:space", oElement.xmlspace);
                    svgNewElement.addEventListener("mousedown",_oClassOwner.trap,false);
                    var textNode = document.createTextNode(oElement.text);
                    svgNewElement.appendChild(textNode);
                    _svgElements.appendChild(svgNewElement);
                    break;
            }
        }
    }

    /**
     * Evento de remocao de um elemento SVG
     */
    this.onRemoveSVGElement = function(){

        var oLayoutComposer = ModelInstance.getLayoutComposer();
        var oElement = oLayoutComposer.getSelectedElement();
        if(oElement != null) {
            oLayoutComposer.removeElement(oElement.id);
        }
    }

    /**
     * Remove um elemento SVG do layout
     */
    this.removeSVGElement = function(elementId){
        
        if(elementId != null) {
            var svgElement = _svgDocument.getElementById(elementId);
            //remove o elemento SVG
            svgElement.parentNode.removeChild(svgElement);
            //esconde o seletor de elementos
            _oClassOwner.hideSelector();
        }
    }

    /**
     * Edita as propriedades do elemento em SVG
     */
    this.editPropertiesSVGElement = function(oElement){

        if(oElement != null){

            var svgElement = _svgDocument.getElementById(oElement.id);

            switch(oElement.type){

                case EElementType.eTImage:
                    //edita as propriedades de um elemento SVG
                    svgElement.setAttribute("x", oElement.x);
                    svgElement.setAttribute("y", oElement.y);
                    svgElement.setAttribute("width", oElement.width);
                    svgElement.setAttribute("height", oElement.height);
                    svgElement.setAttribute("xlink:href", oElement.href);
                    svgElement.setAttribute("style", oElement.style);
                    break;

                case EElementType.eTLabel:
                    svgElement.setAttribute("x", oElement.x);
                    svgElement.setAttribute("y", oElement.y);
                    svgElement.setAttribute("font-size", oElement.fontSize);
                    svgElement.setAttribute("font-family", oElement.fontFamily);
                    svgElement.setAttribute("fill", oElement.fill);
                    svgElement.setAttribute("fill-opacity", oElement.fillOpacity);
                    svgElement.setAttribute("stroke", oElement.stroke);
                    svgElement.setAttribute("stroke-opacity", oElement.strokeOpacity);
                    svgElement.setAttribute("stroke-width", oElement.strokeWidth);
                    svgElement.setAttribute("text-anchor", oElement.textAnchor);
                    svgElement.setAttribute("style", oElement.style);
                    svgElement.setAttribute("xml:space", oElement.xmlspace);
                    var oldText = _svgDocument.getElementById(oElement.id).childNodes[0];
                    var newText = document.createTextNode(oElement.text);
                    _svgDocument.getElementById(oElement.id).replaceChild(newText, oldText);
                    break;
            }
        }
    }

    /**
     * Reposiciona um elemento SVG sobreposto
     */
    this.onReplaceSVGElement = function(position){

        var oLayoutComposer = ModelInstance.getLayoutComposer();
        var oElement = oLayoutComposer.getSelectedElement();
        if(oElement != null) {
            
            switch(position){

                case EGeneralTypes.eSVGPositionTop:
                    _oClassOwner.putSVGElementToTop(oElement.id);
                    break;

                case EGeneralTypes.eSVGPositionBottom:
                    _oClassOwner.putSVGElementToBottom(oElement.id);
                    break;
            }
        }
    }

    /**
     * Reposiciona um elemento SVG para frente dos demais elementos
     */
    this.putSVGElementToTop = function(elementId){

        var svgElement = _svgDocument.getElementById(elementId);
        svgElement.parentNode.appendChild(svgElement);
    }

    /**
     * Reposiciona um elemento SVG para tras dos demais elementos
     */
    this.putSVGElementToBottom = function(elementId){

        var svgElement = _svgDocument.getElementById(elementId);
        //primeiro testa se nao esta pronto o primeiro no
        if (svgElement.previousSibling) {
            //insere o elemento selecionado antes do primero no
            svgElement.parentNode.insertBefore(svgElement, svgElement.parentNode.firstChild);
        }
    }

    /**
     * Esconde o seletor de elemento
     */
    this.hideSelector = function() {
        
        var svgBoxSelector = _svgDocument.getElementById("boxSelector");
        var svgVertexResizerNW = _svgDocument.getElementById("vertexResizer_nw");
        var svgVertexResizerNE = _svgDocument.getElementById("vertexResizer_ne");
        var svgVertexResizerSW = _svgDocument.getElementById("vertexResizer_sw");
        var svgVertexResizerSE = _svgDocument.getElementById("vertexResizer_se");
        
        svgBoxSelector.setAttribute("display", "none");
        svgVertexResizerNW.setAttribute("display", "none");
        svgVertexResizerNE.setAttribute("display", "none");
        svgVertexResizerSW.setAttribute("display", "none");
        svgVertexResizerSE.setAttribute("display", "none");
    }
    
    /**
     * Mostra o seletor de elemento
     */
    this.showSelector = function() {
        
        var svgBoxSelector = _svgDocument.getElementById("boxSelector");
        var svgVertexResizerNW = _svgDocument.getElementById("vertexResizer_nw");
        var svgVertexResizerNE = _svgDocument.getElementById("vertexResizer_ne");
        var svgVertexResizerSW = _svgDocument.getElementById("vertexResizer_sw");
        var svgVertexResizerSE = _svgDocument.getElementById("vertexResizer_se");

        var oLayoutComposer = ModelInstance.getLayoutComposer();
        var oElement = oLayoutComposer.getSelectedElement();
        var displayStatus = "none";
        //define quais tipos de elemento podem ser redimensionados,
        //habilitando ou desabilitando os vertices de redimensionamento
        if(oElement != null) {

            switch(oElement.type) {

                case EElementType.eTImage:
                    displayStatus = "inline";
                    break;
                    
                case EElementType.eTLabel:
                    displayStatus = "inline";
                    break;
            }
        }
        
        svgBoxSelector.setAttribute("display", "inline");
        svgVertexResizerNW.setAttribute("display", displayStatus);
        svgVertexResizerNE.setAttribute("display", displayStatus);
        svgVertexResizerSW.setAttribute("display", displayStatus);
        svgVertexResizerSE.setAttribute("display", displayStatus);
    }

    /**
     * Evento de interacao (clique do mouse) do usuario sobre a area de layout
     */
    this.onClickSVGLayout = function(){

        var oLayoutProject = ModelInstance.getLayoutProject();

        //se o projeto esta aberto
        if(oLayoutProject.projectIsOpened()) {
            var oLayoutComposer = ModelInstance.getLayoutComposer();
            var oUIProperties = UIInstance.getUIPropertiesInstance();
            //atualiza as propriedades do layout
            oLayoutComposer.editPropertiesLayout(oLayoutComposer.getLayout());
            oUIProperties.showProperties();
        }
    }

    /**
     * Edita as propriedades do layout em SVG
     */
    this.editPropertiesSVGLayout = function(oLayout){

        var svgLayout = _svgDocument.getElementById(oLayout.id);
        svgLayout.setAttribute("x", oLayout.x);
        svgLayout.setAttribute("y", oLayout.y);
        svgLayout.setAttribute("width", oLayout.width);
        svgLayout.setAttribute("height", oLayout.height);
        svgLayout.setAttribute("fill", oLayout.fill);
        svgLayout.setAttribute("stroke", oLayout.stroke);
        svgLayout.setAttribute("stroke-width", oLayout.strokeWidth);
        _svgContent.setAttribute("width", svgLayout.getAttributeNS(null, "width"));
        _svgContent.setAttribute("height", svgLayout.getAttributeNS(null, "height"));
        document.getElementById("layout").setAttribute("width", (svgLayout.getAttributeNS(null, "width") + EGeneralTypes.eUnitPx) );
        document.getElementById("layout").setAttribute("height", (svgLayout.getAttributeNS(null, "height") + EGeneralTypes.eUnitPx) );
    }

    this.getElementTypeToDraw = function() {
        return _elementTypeToDraw;
    }

    this.setElementTypeToDraw = function(elementType) {
        _elementTypeToDraw = elementType;
    }

    /**
     * Extrai o conteudo SVG em formato string
     */
    this.extractSVGContent = function(){

        var strSVGContent = "";

        if (_svgContent != null) {
            
            try {
                var serializer = new XMLSerializer();
                strSVGContent = serializer.serializeToString(_svgContent);
            }
            catch (exception) {
                try {
                    //IE
                    strSVGContent = _svgContent.xml;
                    alert(strSVGContent);
                }
                catch (exception) {
                    alert(EAppInfoMessages.eGenerateMapLayoutFailed + EAppInfoMessages.eSerialSVGContentFailed);
                }
            }
        }

        return strSVGContent;
    }

    /**
     * Converte os dados do atributo "d", do tipo de
     * elemento "path" (nativo do SVG), em um conjunto de vertices
     *
     * @param {String} Ex. formato de entrada: "M0,1 L0,2 0,3 0,4z"
     * @return {Array} Ex. formato de saida: [0,1,0,2,0,3,0,4]
     */
    this.parseDPathToVertexes = function(strDPath){

        var strIn="", strOut="";

        strIn = strDPath;
        for(var i=0; i < strIn.length; i++){
            if( (strIn[i] != 'M') && (strIn[i] != 'L') && (strIn[i] != 'z') ){
                strOut = strOut + strIn[i];
            }
        }
        var aVertexes = strOut.split(" ");
        strOut = aVertexes.join();
        aVertexes = strOut.split(",");
        aVertexes.pop();
        return aVertexes;
    }

    /**
     * Converte um conjunto de vertices em formato de dados do atributo "d",
     * do tipo de elemento "path" (nativo do SVG)
     *
     * @param {Array} Ex. formato de entrada: [0,1,0,2,0,3,0,4]
     * @return {String} Ex. formato de saida: "M0,1 L0,2 0,3 0,4z"
     */
    this.parseVertexesToDPath = function(aVertexes){

        var strDPath = "";

        for(var i=0; i < aVertexes.length; i=i+2){
            switch(i){
                case 0:
                    strDPath = "M" + aVertexes[i] + "," + aVertexes[i+1];
                    break;
                default:
                    strDPath = strDPath + " L" + aVertexes[i] + "," + aVertexes[i+1];
            }
        }
        if(strDPath != ""){
            strDPath = strDPath + " z";
        }
        return strDPath;
    }

    /**
     * Converte coordenadas do mouse em coordenadas SVG
     *
     * @deprecated
     * @param {Object} objeto correspondente a um elemento SVG
     * @param {Float} coordenada X da posicao do mouse
     * @param {Float} coordenada Y da posicao do mouse
     * @return {Object} objeto correspondente as coordenadas do ponto SVG
     */
    this.mousePointToSVGPoint = function(svgElement, coordX, coordY){
        var matrix = svgElement.getScreenCTM();
        var point = _svgDocument.documentElement.createSVGPoint();
        point.x = coordX;
        point.y = coordY;
        return point.matrixTransform(matrix.inverse());
    }

    /**
     * Obtem valores da matriz de um elemento SVG,
     * a partir de uma string que corresponde a matriz
     *
     * @param {String} Ex. formato de entrada: "matrix(1,0,0,1,0,0)"
     * @return {Array} Ex. formato de saida: [1,0,0,1,0,0]
     */
    this.matrixStringToMatrixValues = function(strMatrix) {

        var strIn="", strOut="";
        var aMatrixValues = [1,0,0,1,0,0];  //matriz default

        strIn = strMatrix;
        var index = strIn.indexOf("matrix(");
        if(index == 0) {
            strOut = strIn.slice(7,-1);
            aMatrixValues = strOut.split(",");
            aMatrixValues.pop();
        }
        return aMatrixValues;
    }

    /**
     * Chamada do inicializador da classe
     */
    this.init();
}
